home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-02-20 | 11.8 KB | 308 lines | [TEXT/CWIE] |
-
- #include "TransactionSuite.h"
- #include "Transaction.h"
- #include "MoreAEM.h"
- #include "EventHandlerTable.h"
-
-
-
-
- TTransactionList TTransactionSuite::gTransactionList;
- long TTransactionSuite::gTransactionID = 1;
-
- //----------------------------------------------------------------------------------------
- // TTransactionSuite::InstallAEHandlers:
- //----------------------------------------------------------------------------------------
- void TTransactionSuite::InstallAEHandlers(TEventHandlerTable& eventTable)
- {
- //
- // The event handler table will create a UPP if it needs to
- //
- FailErr(eventTable.InstallHandler(kAEMiscStandards, kAEBeginTransaction, (EventHandlerProcPtr) &TTransactionSuite::BeginTransaction, 0));
- FailErr(eventTable.InstallHandler(kAEMiscStandards, kAEEndTransaction, (EventHandlerProcPtr) &TTransactionSuite::EndTransaction, 0));
- FailErr(eventTable.InstallHandler(kAEMiscStandards, kAETransactionTerminated, (EventHandlerProcPtr) &TTransactionSuite::TerminateTransaction, 0));
- } // TCoreSuite::InstallAEHandlers
-
- //----------------------------------------------------------------------------------------
- // TTransactionSuite::GenerateNewTransactionID
- //----------------------------------------------------------------------------------------
- SInt32 TTransactionSuite::GenerateNewTransactionID()
- {
- return ++gTransactionID;
- }
-
- //----------------------------------------------------------------------------------------
- // TTransactionSuite::BeginTransaction:
- //
- // This event is received at the beginning of a new transaction.
- //----------------------------------------------------------------------------------------
- pascal OSErr TTransactionSuite::BeginTransaction(TAEvent& ae, TAEvent& reply, long /* refCon */)
- {
- // DebugStr("\pTTransactionSuite::BeginTransaction");
- TAETransaction t(ae, reply);
- OSErr err = noErr;
-
- //
- // AppleScript inserts a parameter keySubjectAttr in the
- // transaction, but I'm not sure how to specify what data
- // it should contain (it's a null descriptor by default).
- // If you say:
- //
- // with transaction "some text"
- //
- // then "some text" will be in the direct object of the
- // transaction; of course, other data types (e.g. object
- // specifiers) could be used here as well, and might be
- // useful for some types of transactions.
- //
- // It might be useful to associate the subject of the
- // transaction with the transaction object so that it
- // (the subject) may be returned along with the error
- // code when an event fails due to a conflict with some
- // other transaction.
- //
-
- //
- // We don't expect that there will be a transaction associated
- // with this event, but we'll test for it anyway
- //
- TTransaction* transaction = TTransactionSuite::GetTransactionFromEvent(t);
- if(transaction == nil)
- {
- long transactionID = TTransactionSuite::GenerateNewTransactionID();
- TTransactionSuite::BeginEventTransaction(t, kMultiEventTransaction, transactionID, true);
-
- //
- // Put the transaction ID into the result and also a 'keyTransactionIDAttr'
- // (AppleScript looks at this parameter--not attribute--in the reply)
- //
- reply.PutSInt32Parameter(keyTransactionIDAttr, transactionID);
- reply.PutSInt32Parameter(keyAEResult, transactionID);
- }
-
- return err;
- }
-
-
- //----------------------------------------------------------------------------------------
- // TTransactionSuite::EndTransaction:
- //
- // This event is received at the end of a successful transaction
- //----------------------------------------------------------------------------------------
- pascal OSErr TTransactionSuite::EndTransaction(TAEvent& ae, TAEvent& reply, long /* refCon */)
- {
- // DebugStr("\pTTransactionSuite::EndTransaction");
- TAETransaction t(ae, reply);
- OSErr err = noErr;
-
- //
- // Get the transaction from the event and commit its changes.
- //
- TTransaction* transaction = TTransactionSuite::GetTransactionFromEvent(t);
- if(transaction != nil)
- {
- TTransactionSuite::EndEventTransaction(t, true);
- }
-
- return err;
- }
-
- //----------------------------------------------------------------------------------------
- // TTransactionSuite::TerminateTransaction:
- //
- // This event is received when a transaction is aborted due to some failure
- //----------------------------------------------------------------------------------------
- pascal OSErr TTransactionSuite::TerminateTransaction(TAEvent& ae, TAEvent& reply, long /* refCon */)
- {
- // DebugStr("\pTTransactionSuite::TerminateTransaction");
- TAETransaction t(ae, reply);
- OSErr err = noErr;
-
- TTransaction* transaction = TTransactionSuite::GetTransactionFromEvent(t);
- if(transaction != nil)
- {
- TTransactionSuite::TerminateEventTransaction(t, true);
- }
-
- return err;
- }
-
- //----------------------------------------------------------------------------------------
- // TTransactionSuite::GetTransactionFromEvent
- //
- // Look up the transaction associated with the current event. Return nil if there
- // is no item in the list that matches the event's transaction ID.
- //----------------------------------------------------------------------------------------
- TTransaction* TTransactionSuite::GetTransactionFromEvent(const TAETransaction& t)
- {
- TTransaction* transaction = (TTransaction*)t.TransactionCache();
- if(transaction == nil)
- {
- transaction = gTransactionList.FindTransaction(t.GetTransactionID());
- ((TAETransaction&)t).SetTransactionCache(transaction);
- }
-
- return transaction;
- }
-
- //----------------------------------------------------------------------------------------
- // TTransactionSuite::BeginEventTransaction
- //
- // An event handler calls this method to fetch the transaction associated with
- // the given AppleEvent. If the AppleEvent is not part of any transaction, then
- // by default, a new transaction is created for the exclusive use of this event.
- // If the event handler does not require a transaction (if, for example, the event
- // never modifies the state of any transaction-controlled object), then it can
- // pass 'false' for transactionAlwaysNeeded to suppress creation of the temporary
- // transaction.
- //
- // n.b. Read-only event handlers should always use the transaction associated with
- // an event so that it can 'see' changes made by previous events in the same
- // transaction.
- //----------------------------------------------------------------------------------------
- void TTransactionSuite::BeginEventTransaction(TAETransaction& t, Boolean transactionAlwaysNeeded /*= true*/)
- {
- BeginEventTransaction(t, kSingleEventTransaction, TTransactionSuite::GenerateNewTransactionID(), transactionAlwaysNeeded);
- }
-
- //----------------------------------------------------------------------------------------
- // TTransactionSuite::BeginEventTransaction
- //
- // Protected version of above method; a transactionType of kMultiEventTransaction
- // can only be provided by the BeginTransaction event.
- //----------------------------------------------------------------------------------------
- void TTransactionSuite::BeginEventTransaction(TAETransaction& t, AETransactionType transactionType, SInt32 transactionID, Boolean transactionAlwaysNeeded /*= true*/)
- {
- // DebugStr("\pTTransactionSuite::BeginEventTransaction");
- TTransaction* transaction = TTransactionSuite::GetTransactionFromEvent(t);
-
- if((transaction == nil) && transactionAlwaysNeeded)
- {
- transaction = new TTransaction;
- t.SetTransactionCache(transaction);
- gTransactionList.AddTransaction(transaction, transactionID, transactionType);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // TTransactionSuite::EndEventTransaction
- //
- // An event hander calls this method when it completes sucessfully. If this event
- // is part of some transaction, then no action is taken at this time. If the event
- // is being executed outside of any transaction, though, then the changes it affected
- // are committed and the transaction is deleted.
- //----------------------------------------------------------------------------------------
- void TTransactionSuite::EndEventTransaction(TAETransaction& t, Boolean alwaysDeleteTransaction)
- {
- // DebugStr("\pTTransactionSuite::EndEventTransaction");
- TTransaction* transaction = TTransactionSuite::GetTransactionFromEvent(t);
- if(transaction != nil)
- {
- //
- // If this event was not associated with any specific
- // transaction, then there will never be an end
- // transaction event--we'd better commit our changes
- // and delete the transaction right now.
- //
- if((gTransactionList.TransactionType(transaction) == kSingleEventTransaction) || (alwaysDeleteTransaction == true))
- {
- // DebugStr("\pCommit changes and delete transaction");
- transaction->CommitChanges();
- gTransactionList.RemoveTransaction(transaction);
- delete transaction;
- t.SetTransactionCache(nil);
- }
- }
- }
-
- //----------------------------------------------------------------------------------------
- // TTransactionSuite::TerminateEventTransaction
- //
- // An event handler calls this method if the event failed for some reason.
- // This method will back out all changes and delete the transaction, if necessary.
- //----------------------------------------------------------------------------------------
- void TTransactionSuite::TerminateEventTransaction(TAETransaction& t, Boolean alwaysDeleteTransaction)
- {
- // DebugStr("\pTTransactionSuite::TerminateEventTransaction");
- TTransaction* transaction = TTransactionSuite::GetTransactionFromEvent(t);
- if(transaction != nil)
- {
- //
- // Always discard our changes up to now, even if we're in the
- // middle of a transaction. We don't expect to get any more
- // events in this transaction, but if we do, we will begin
- // making changes again from the beginning.
- //
- // If we aren't in a transaction, then we'd better delete the
- // transaction object right now.
- //
- transaction->DiscardChanges();
- if((gTransactionList.TransactionType(transaction) == kSingleEventTransaction) || (alwaysDeleteTransaction == true))
- {
- gTransactionList.RemoveTransaction(transaction);
- delete transaction;
- t.SetTransactionCache(nil);
- }
- }
- }
-
-
-
- //----------------------------------------------------------------------------------------
- // TTransactionList::AddTransaction
- //----------------------------------------------------------------------------------------
- void TTransactionList::AddTransaction(TTransaction* t, long transactionID, AETransactionType transactionType)
- {
- fTransactionList.InsertAtEnd(TTransactionRecord(t, transactionID, transactionType));
- }
-
- //----------------------------------------------------------------------------------------
- // TTransactionList::FindTransaction
- //----------------------------------------------------------------------------------------
- TTransaction* TTransactionList::FindTransaction(long transactionID) const
- {
- TTransaction* t = nil;
- for(AnIteratorOfAListOf<TTransactionRecord> iter((AListOf<TTransactionRecord>*)&fTransactionList); iter.More(); iter.Next())
- {
- if(iter.Current().TransactionID() == transactionID)
- {
- t = iter.Current().Transaction();
- break;
- }
- }
-
- return t;
- }
-
- //----------------------------------------------------------------------------------------
- // TTransactionList::RemoveTransaction
- //----------------------------------------------------------------------------------------
- void TTransactionList::RemoveTransaction(TTransaction* transaction)
- {
- for(AnIteratorOfAListOf<TTransactionRecord> iter(&fTransactionList); iter.More(); iter.Next())
- {
- if(iter.Current().Transaction() == transaction)
- {
- iter.RemoveCurrent();
- }
- }
- }
-
- //----------------------------------------------------------------------------------------
- // TTransactionList::TransactionType
- //----------------------------------------------------------------------------------------
- AETransactionType TTransactionList::TransactionType(TTransaction* transaction) const
- {
- AETransactionType t = kNoSuchTransaction;
- for(AnIteratorOfAListOf<TTransactionRecord> iter((AListOf<TTransactionRecord>*)&fTransactionList); iter.More(); iter.Next())
- {
- if(iter.Current().Transaction() == transaction)
- {
- t = iter.Current().TransactionType();
- break;
- }
- }
-
- return t;
- }
-